﻿//Ext.StoreMgr本质上是一个Ext.AbstractManager对象，
//并且重写了Ext.AbstractManager的若干方法

Ext.ModelMgr = new Ext.AbstractManager({
    typeName: 'mtype', //Ext.AbstractManager的typeName为'type',
                       //Ext.PluginMgr的typeName为'ptype'
    defaultProxyType: 'ajax',
    associationStack: [], //关联对象数组

    //注册一个model，name：model名称，config：model各字段属性
    registerType: function (name, config) {

        var PluginMgr = Ext.PluginMgr,
            plugins = PluginMgr.findByType('model', true), //返回所有类型为'model'，且isDefault属性为真的插件
            fields = config.fields || [],                  //参数中传人的字段配置对象
            associations = config.associations || [],      //与当前模型关联的模型的信息，包括一对多（{type: 'hasMany'}）和多对一（{ type: 'belongsTo' }）
            belongsTo = config.belongsTo,                  //该模型所属的模型名称
            hasMany = config.hasMany,                      //该模型包含的模型信息
            extendName = config.extend,                    //当前模型要继承的模型类别
            modelPlugins = config.plugins || [],           //模型插件
            association, model, length, i,
            extendModel, extendModelProto, extendValidations, proxy;


        //把belongsTo属性的信息整理后统一放到associations属性中
        if (belongsTo) {
            if (!Ext.isArray(belongsTo)) {//把belongsTo统一成数组
                belongsTo = [belongsTo];
            }

            for (i = 0; i < belongsTo.length; i++) {//把belongsTo中所指的各模型配置成标准对象放入associations数组中
                association = belongsTo[i];

                if (!Ext.isObject(association)) {
                    association = { model: association };
                }
                Ext.apply(association, { type: 'belongsTo' });

                associations.push(association);
            }

            delete config.belongsTo;
        }
        //把hasMany属性的信息整理后统一放到associations属性中
        if (hasMany) {
            if (!Ext.isArray(hasMany)) {
                hasMany = [hasMany];
            }

            for (i = 0; i < hasMany.length; i++) {
                association = hasMany[i];

                if (!Ext.isObject(association)) {
                    association = { model: association };
                }

                Ext.apply(association, { type: 'hasMany' });

                associations.push(association);
            }

            delete config.hasMany;
        }

        //如果指定了模型类名
        if (extendName) {
            extendModel = this.types[extendName];//通过extendName获取具体的模型类
            extendModelProto = extendModel.prototype;//model的原型对象
            extendValidations = extendModelProto.validations; //model原型对象的验证

            proxy = extendModel.proxy;
            fields = extendModelProto.fields.items.concat(fields);
            associations = extendModelProto.associations.items.concat(associations);
            config.validations = extendValidations ? extendValidations.concat(config.validations) : config.validations;
        }
        //否则默认为Ext.data.Model
        else {
            extendModel = Ext.data.Model;
            proxy = config.proxy;//代理类为参数传过来的代理类
        }

        model = Ext.extend(extendModel, config);//model继承自extendModel，并具有配置对象指定的属性

        for (i = 0, length = modelPlugins.length; i < length; i++) {//处理插件，将模型插件放入plugins数组中
            plugins.push(PluginMgr.create(modelPlugins[i]));
        }

        this.types[name] = model;//以模型名称为键注册一个模型类

        //给新的模型类重写一些属性
        Ext.override(model, {
            plugins: plugins,                   //插件
            fields: this.createFields(fields),  //创建字段对象
            associations: this.createAssociations(associations, name)//创建并填充关联model集合
        });

        model.modelName = name; //model的类名，name是从参数中传过来的

        //为新模型设置代理
        Ext.data.Model.setProxy.call(model, proxy || this.defaultProxyType); //defaultProxyType: 'ajax'

        model.getProxy = model.prototype.getProxy;//继承原型的getProxy方法

        model.load = function () {//继承Model类的load方法
            Ext.data.Model.load.apply(this, arguments);
        };

        for (i = 0, length = plugins.length; i < length; i++) {
            plugins[i].bootstrap(model, config);//启动model插件
        }

        model.defined = true;
        this.onModelDefined(model);//注册先前未注册的管理model集合

        return model;
    },

    //遍历associationStack数组，如果发现新建模型在该数组中有对应名，说明新建模型是其他模型的关联模型，
    //于是通过新建模型的属性找到注册了的主模型，将新建模型对应的关联对象加入主模型的关联对象数组中
    onModelDefined: function (model) {
        var stack = this.associationStack,
            length = stack.length,
            create = [],
            association, i;

        for (i = 0; i < length; i++) {//遍历从model未注册的关联对象集合
            association = stack[i];

            if (association.associatedModel == model.modelName) {//如果当前元素正是当前新建的model
                create.push(association);
            }
        }

        length = create.length;
        for (i = 0; i < length; i++) {
            this.addAssociation(create[i], this.types[create[i].ownerModel].prototype.associations);
            stack.remove(create[i]);
        }
    },

    //创建并填充关联model集合
    createAssociations: function (associations, name) {
        var length = associations.length,
            i, associationsMC, association;

        associationsMC = new Ext.util.MixedCollection(false, function (association) {//创建关联model集合，以model名为键
            return association.name;
        });

        for (i = 0; i < length; i++) {
            association = associations[i];
            //给关联model添加属性
            Ext.apply(association, {
                ownerModel: name,                 //ownerModel为主model的名称
                associatedModel: association.model//associatedModel为从model的名称
            });

            if (this.types[association.model] == undefined) {//如果从model未注册
                this.associationStack.push(association);//向associationStack添加从关联对象信息
            } else {
                this.addAssociation(association, associationsMC);//向associationsMC集合添加具体的已分类的关联模型实例
            }
        }

        return associationsMC;//返回关联model集合
    },

    //向associationsMC集合添加具体的已分类的关联模型实例
    addAssociation: function (association, associationsMC) {
        var type = association.type;

        if (type == 'belongsTo') {
            associationsMC.add(new Ext.data.BelongsToAssociation(association));
        }

        if (type == 'hasMany') {
            associationsMC.add(new Ext.data.HasManyAssociation(association));
        }

        if (type == 'polymorphic') {
            associationsMC.add(new Ext.data.PolymorphicAssociation(association));
        }
    },

    //为模型创建字段对象
    createFields: function (fields) {
        var length = fields.length,
            i, fieldsMC;

        //创建字段集合，其中以字段名为键
        fieldsMC = new Ext.util.MixedCollection(false, function (field) {
            return field.name;
        });

        for (i = 0; i < length; i++) {
            fieldsMC.add(new Ext.data.Field(fields[i]));//创建字段对象并放入集合
        }

        return fieldsMC;//返回字段集合
    },

    //根据id获取model类
    getModel: function (id) {
        var model = id;
        if (typeof model == 'string') {
            model = this.types[model];
        }
        return model;
    },

    //创建一个model实例
    create: function (config, name, id) {
        //如果name是一个函数，说明是构造函数，因此取name，
        //否则如果name有值，表示model名，因此根据model名取model类，
        //如果name没有值，则取config的model名，再取model类
        var con = typeof name == 'function' ? name : this.types[name || config.name];

        return new con(config, id);
    }
});


Ext.regModel = function () {
    return Ext.ModelMgr.registerType.apply(Ext.ModelMgr, arguments);
};